// wait_group 实现有条件的等待
#include <workflow/WFFacilities.h>
#include <workflow/WFTaskFactory.h>
#include <workflow/WFHttpServer.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
using std::cout;
using std::cerr;
using std::string;
struct SeriesContext{
    string username;
    string password;
    protocol::HttpResponse *resp;
};
static WFFacilities::WaitGroup waitGroup(1);
void handler(int signum){
    cout << "done\n";
    waitGroup.done();
}
void serverCallback(WFHttpTask * serverTask){
    cout << "serverCallback is called!\n";
}
void redisCallback(WFRedisTask * redisTask){
    cout << "redisCallback is called!\n";
    protocol::RedisRequest *req = redisTask->get_req();
	protocol::RedisResponse *resp = redisTask->get_resp();
	int state = redisTask->get_state();
	int error = redisTask->get_error();
    // val用来保存redis执行的结果
	protocol::RedisValue val;
    switch (state){
	case WFT_STATE_SYS_ERROR:
		cerr <<"system error: " << strerror(error) << "\n";
		break;
	case WFT_STATE_DNS_ERROR:
		cerr <<"DNS error: "  << gai_strerror(error) << "\n";
		break;
	case WFT_STATE_SSL_ERROR:
		cerr <<"SSL error\n";
		break;
	case WFT_STATE_TASK_ERROR:
		cerr <<"Task error\n";
		break;
	case WFT_STATE_SUCCESS:
    	resp->get_result(val);// 将redis的执行结果保存起来
		if (val.is_error()){
		   cerr <<  "Error reply. Need a password?\n";
		   state = WFT_STATE_TASK_ERROR;
		}
		break;
	}
	if (state != WFT_STATE_SUCCESS){
		cerr <<  "Failed. Press Ctrl-C to exit.\n";
		return;
	}
    // 从context中取出一些信息
    SeriesContext * context = static_cast<SeriesContext *>(series_of(redisTask)->get_context());
	if(val.is_string() && val.string_value() == context->password){
        context->resp->append_output_body("<html>login success!</html>");
		
	}
    else{
        context->resp->append_output_body("<html>login failed!</html>");
    }
    cout << "redisCallback is done!\n";
}
void readCallback(WFFileIOTask * readTask){
    FileIOArgs* args =  readTask->get_args();
    cout << "buf = " << (char *)args->buf << "\n";
    cout << "count = " << args->count << "\n";
    SeriesContext * context = static_cast<SeriesContext *>(series_of(readTask)->get_context());
    context->resp->append_output_body(args->buf,args->count);
}
void process(WFHttpTask * serverTask){
    //serverTask是服务端任务 是分离的
    cout << "process is called!\n";
    // 读取请求 写入响应
    protocol::HttpRequest *req = serverTask->get_req();
    protocol::HttpResponse *resp = serverTask->get_resp();
    // 提取请求的信息
    string method = req->get_method();
    string url = req->get_request_uri();
    string path = url.substr(0,url.find("?"));
    // 准备好需要共享的数据 context
    SeriesContext * context = new SeriesContext;
    context->resp = resp;
    series_of(serverTask)->set_context(context);
    if(method == "GET" && path == "/login"){
        int fd = open("postform.html",O_RDWR);
        ///char buf[1024] = {0};
        char *buf = new char[1024]{0};
        WFFileIOTask * readTask = WFTaskFactory::create_pread_task(fd,buf,1024,0,readCallback);
        series_of(serverTask)->push_back(readTask);
    }
    else if(method == "POST" && path == "/login"){
        //string query = url.substr(url.find("?")+1);
        const void *body;
        size_t length;
        req->get_parsed_body(&body,&length);
        string query = static_cast <const char *>(body);
        string nameKV = query.substr(0,query.find("&"));
        string name = nameKV.substr(nameKV.find("=")+1);
        string passwordKV = query.substr(query.find("&")+1);
        string password = passwordKV.substr(passwordKV.find("=")+1);
        /// 将password存入series的context中
        context->password = password;
        context->username = name;
        //创建redis任务
        WFRedisTask * redisTask = WFTaskFactory::create_redis_task("redis://127.0.0.1:6379",10,redisCallback);
        redisTask->get_req()->set_request("HGET",{"60user",name});
        series_of(serverTask)->push_back(redisTask);
    }




    // serverTask->set_callback(serverCallback);
    // cout << "process is done!\n";
}
int main(){
    signal(SIGINT,handler);
    // 构造了一个server对象
    WFHttpServer server(process);
    // 开启监听
    if(server.start(1234) == 0){
        cout << "server start success!\n";
        waitGroup.wait(); //阻塞住主线程
        server.stop(); // 停止监听
    }
    else{
        perror("server start");
        return -1;
    }
    return 0;
}
